<script setup lang="ts">
import { ElTable, ElTableColumn, ElPagination, ElButton, vLoading, ElTooltip, ElSelectV2, ElInput, ElForm, ElFormItem, ElTag } from "element-plus"
import Nifi from "../../nifi";
import { computed, h, reactive, ref, toRef, watch } from "vue";
import { chunk } from "lodash-es";

// @ts-ignore
import ConfigElem from "./config.vue"
import { IPackNifi } from "src/inter";
import AddEl from "./add.vue"
import {t} from "../../i18n/index"
interface Props {
    nifi: Nifi
    id: string
    search?: string
    box:IPackNifi.DialogEl
}
//
const emits = defineEmits<{ goTo: [id: string, name: string, search?: string] }>()
const props = defineProps<Props>();
const { nifi, id,box } = props;
const sn = toRef(props, 'search')
//
const isDisabled = computed(() => nifi.graph.mode.value == 'prod')
const model = reactive<{ name: string, description: string, id: string, inheritedParameterContexts: string[] }>({ name: '', description: '', id: '', inheritedParameterContexts: [] })
const parameters = reactive<any[]>([])
const boundProcessGroups = reactive<any[]>([])
const parameterNames = reactive<string[]>([])
//
const loading = ref(false)
const refresh = async (force = false) => {
    loading.value = true;
    const res = await nifi.Parameters.get(id,force);
    if (res) {
        const c = res.component;
        //
        model.name = c.name;
        model.id = c.id;
        model.description = c.description;
        parameters.length = 0;
        parameters.push(...nifi.Parameters.getParameters(res))
        parameterNames.length = 0;
        parameterNames.push(...parameters.filter(t => t.parameterContext.id == id).map(t => t.name))
        boundProcessGroups.length = 0;
        boundProcessGroups.push(...c.boundProcessGroups);
        // model.inheritedParameterContexts = [];
        model.inheritedParameterContexts = Array.from(new Set<string>(c.inheritedParameterContexts.map((d: any) => d.id)))
    }
    //
    loading.value = false;
}

const refreshParameters = async () => {
    const res = await nifi.Parameters.get(id);
}
//

refresh(true);
//
const options = computed(() => { return nifi.flow.parameterContexts?.filter(d => d.id != id).map((d: any) => ({ label: d.component.name, value: d.id })) })
//
//
const pages = reactive({ pageNum: 1, pageSize: 10, total: 0, sizes: [], layout: "prev, pager, next, total" })
const search = ref(props.search || '')
//
const currentRow = ref<any>()
//
const list = computed(() => {
    let l = parameters;
    const s = search.value.toLowerCase();
    l = l.filter((d: any) => d.name?.toLowerCase().includes(s) || d.value?.toLowerCase().includes(s))
    pages.total = l.length;
    return chunk(l, pages.pageSize)
})

const data = computed(() => list.value[pages.pageNum - 1] || [])
//
//
const tableRef = ref<InstanceType<typeof ElTable>>();
//
const clearQuery = () => {
    search.value = "";
}
//
const handleRowClick = (row: any) => {
    currentRow.value = row;
    console.log(row)
}
//
const baseFormRef = ref<InstanceType<typeof ElForm>>()
//
const saveLoading = ref(false)
const handleSave = async () => {
    //
    saveLoading.value = true;
    try {
        await baseFormRef.value?.validate()
    } catch (error) {
        console.error(error)
        return;
    }
    //
    const inheritedParameterContexts = model.inheritedParameterContexts.map(id => nifi.flow.parameterContexts.find(d => d.id == id)).map(d => ({ id: d.id, component: { id: d.id, name: d.component.name } }));
    const parameters = await diffParmeters();
    const component = { name: model.name, description: model.description, id: model.id, inheritedParameterContexts, parameters, boundProcessGroups }
    //
    const td = await nifi.Parameters.get(id);
    const data = { ...td, component };
    //
    await nifi.Parameters.update(model.id, data)
    //
    await refresh(true);
    saveLoading.value = false;
}

const diffParmeters = async () => {

    const tp = parameters.filter(d => d.parameterContext.id == model.id);
    //
    const res = await nifi.Parameters.get(model.id);
    const sp: any[] = nifi.Parameters.getParameters(res).filter((d: any) => d.parameterContext.id == model.id);
    const spn = sp.map(d => d.name)
    const tpn = tp.map(d => d.name)
    const result: any[] = [];
    for (const n of new Set([...tpn, ...spn])) {
        const t = tp.find(d => d.name == n);
        const s = sp.find(d => d.name == n);
        if (!t && s) {
            result.push({ parameter: { name: n } })
        }
        else if (!s || t.value != s.value) {
            result.push({ parameter: { sensitive: t.sensitive, description: t.description, name: n, value: t.value } })
        }
    }
    return result;
}

const check = async () => {}


const handleReset = () => {
    clearQuery()
}

const handleConfig = (row: any) => { }

const handleDelete = (row: any) => {
    const i = parameters.indexOf(row)
    parameters.splice(i, 1);
}
//
const handleGoTo = (row: any) => {
    const s = row.name;
    const c = row.parameterContext.component;
    emits('goTo', c.id, c.name, s);
}

const handleRefresh = () => {
    refresh();
}

const handleInheriteChange = async (vals:string[]) => {
    const sd = await nifi.Parameters.get(id);
    const sp = nifi.Parameters.getSelfParameters(sd)
    const spns = sp.map((t:any) => t.name)
    const eds = await Promise.all(Array.from(new Set([...vals])).map(id => nifi.Parameters.get(id)))
    const list = new Array().concat(...eds.map(d => nifi.Parameters.getSelfParameters(d))).filter((t:any) => !spns.includes(t.name));
    parameters.length = 0;
    parameters.push(...sp,...list)
}

const handleAdd = () => {
    nifi.box.dialog((box) => h(AddEl,{names:parameterNames,box,onSubmit:(d) => {
        parameters.unshift({...d,parameterContext:{id}})
    }}))
}

const handleEdit = (row: any) => {
    nifi.box.dialog((box) => h(AddEl,{names:parameterNames,box,row,onSubmit:({description,value}) => {
        row.description = description;
        row.value = value;
    }}))
}

const handleGoToGroup = async (id:string) => {
    nifi.group.refresh(id)
    box.close()
}

const handleGoToCell = async (cd:any) => {
    nifi.group.goToCell(cd.processGroupId,cd.id)
    box.close()
}

watch(sn, (v) => {
    if (v) {
        search.value = v;
        const row = parameters.filter(d => d.name == v)[0];
        if (row) {
            tableRef.value?.setCurrentRow(row)
        }
    } else {
        search.value = '';
    }
})

watch(parameters, () => {
    if (search.value) {
        const row = parameters.filter(d => d.name == search.value)[0];
        row && tableRef.value?.setCurrentRow(row)
    }
})


</script>


<template>
    <div class="flex flex-col gap-8px w-full h-full overflow-hidden" v-loading="loading">
        <div class="h-40px flex w-full justify-between items-center">
            <ElButton type="success" @click="handleRefresh">{{t('param-list-btn-refresh')}}</ElButton>
            <div class="flex gap-8px items-center">
                <ElInput class="important-w-200px " :placeholder="t('param-list-search-placeholder')" v-model="search" clearable></ElInput>
                <ElButton :title="t('param-list-addattr-title')" type="success" @click="handleAdd">
                    <div class="i-fluent:add-12-filled w-1em h-1em"></div>
                </ElButton>
                <ElButton type="primary" @click="handleSave" :loading="saveLoading">{{t('param-list-btn-save')}}</ElButton>
            </div>

        </div>
        <div class="flex-1 overflow-hidden flex gap-24px">
            <div class="w-400px h-full flex flex-col box-border overflow-hidden">
                <div class="h-160px">
                    <ElForm ref="baseFormRef" :model="model" class="w-full" label-position="left" >
                        <ElFormItem :label="t('param-list-name-label')" prop="name"
                            :rules="[{ required: true, message: t('param-list-name-rule'), trigger: 'blur' }]">
                            <ElInput v-model="model.name"></ElInput>
                        </ElFormItem>

                        <ElFormItem :label="t('param-list-inherite-label')">
                            <ElSelectV2 v-model="model.inheritedParameterContexts" :options="options" multiple
                                collapse-tags :teleported="false" clearable @change="handleInheriteChange"></ElSelectV2>
                        </ElFormItem>

                        <ElFormItem :label="t('param-list-desc-label')" prop="description">
                            <ElInput v-model="model.description"></ElInput>
                        </ElFormItem>
                    </ElForm>
                </div>
                <fieldset v-if="boundProcessGroups.length > 0"
                    class="flex-1 overflow-hidden  p-12px p-t-2px rd-4px b-gray-300 b-solid">
                    <legend>{{t('param-list-legend-comps')}}</legend>
                    <div class="h-full flex flex-wrap overflow-auto gap-1">
                        <ElTag class="cursor-pointer" v-for="item in boundProcessGroups" type="success" @click="handleGoToGroup(item.id)">{{ item.component.name }}</ElTag>
                    </div>
                </fieldset>
                <fieldset class="flex-1 overflow-hidden p-12px p-t-2px rd-4px b-gray-300 b-solid box-border">
                    <legend class="max-w-300px truncate">{{t('param-list-legend-value')}} [{{ currentRow?.name }}]</legend>
                    <div class="flex flex-wrap h-full overflow-auto gap-1">
                        <ElTag class="cursor-pointer" v-for="item in currentRow?.referencingComponents" @click="handleGoToCell(item.component)" >{{ item.component.name }}</ElTag>
                    </div>
                </fieldset>
            </div>

            <div class="flex-1 overflow-hidden h-full gap-8px flex flex-col">
                <!-- header -->
                <div class="flex-1 overflow-hidden">
                    <ElTable ref="tableRef" class="important-h-full" :data="data" stripe highlight-current-row
                        row-key="name" @current-change="handleRowClick">
                        <ElTableColumn :label="t('param-list-cols-index')" width="80" align="center" fixed>
                            <template #default="{ $index }">{{ pages.pageSize * (pages.pageNum - 1) + $index + 1
                                }}</template>
                        </ElTableColumn>
                        <ElTableColumn :label="t('param-list-cols-name')" min-width="60" show-overflow-tooltip>
                            <template #default="{ row }">
                                <div class="flex items-center justify-between">
                                    {{ row.name }}
                                    <ElTooltip v-if="row.description" :content="row.description" placement="top-start">
                                        <div class="i-pepicons-pop:question w-1em h-1em c-#aaa"></div>
                                    </ElTooltip>
                                </div>

                            </template>
                        </ElTableColumn>
                        <ElTableColumn :label="t('param-list-cols-value-label')" show-overflow-tooltip min-width="100">
                            <template #default="{ row }">
                                <ElInput v-model="row.value" :disabled="row.parameterContext.id != model.id" :placeholder="t('param-list-cols-value-placeholder')" ></ElInput>
                            </template>
                        </ElTableColumn>
                        <!--  -->
                        <ElTableColumn width="80" :label="t('param-list-cols-operate')" fixed="right">
                            <template #default="{ row }">

                                <ElButton v-if="row.parameterContext.id != model.id" :title="t('param-list-cols-operate-goto')" type="primary" link
                                    @click="() => handleGoTo(row)">
                                    <div class="i-icon-park-twotone:hand-right w-1em h-1em"></div>
                                </ElButton>
                                <template v-else>
                                    <ElButton :disabled="isDisabled" :title="t('param-list-cols-operate-edit')" @click="() => handleEdit(row)" link
                                        type="primary">
                                        <div class="i-line-md:edit w-1em h-1em"></div>
                                    </ElButton>
                                    <ElButton :disabled="isDisabled" :title="t('param-list-cols-operate-delete')" @click="() => handleDelete(row)" link
                                        type="danger">
                                        <div class="i-pajamas:remove w-1em h-1em"></div>
                                    </ElButton>
                                </template>
                            </template>
                        </ElTableColumn>
                    </ElTable>
                </div>

                <div class="h-40px flex justify-end items-end">
                    <ElPagination v-model:current-page="pages.pageNum" v-model:page-size="pages.pageSize"
                        :total="pages.total" :page-sizes="pages.sizes" :layout="pages.layout"></ElPagination>
                </div>

            </div>

        </div>

        <!--  -->

    </div>

</template>